import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { SearchModule } from './search.module';

@Component({
  template: `
    <lv-search
      [lvPlaceHolder]="placeHolder"
      [lvLoading]="loading"
      [lvFocus]="focus"
      [lvDisabled]="disabled"
      [lvMaxLength]="maxLength"
      (lvSearch)="search()"
      (lvClear)="clear()"
    ></lv-search>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestSearchComponent {
  placeHolder;
  loading = false;
  focus = false;
  disabled = false;
  maxLength = 100;

  search() {}
  clear() {}
}

describe('SearchComponent', () => {
  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [TestSearchComponent],
        imports: [SearchModule],
        teardown: { destroyAfterEach: false },
      }).compileComponents();
    })
  );

  describe('render', () => {
    let component: TestSearchComponent;
    let fixture: ComponentFixture<TestSearchComponent>;
    const renderComp = fakeAsync(para => {
      for (const [key, value] of Object.entries(para)) {
        component[key] = value;
      }
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      expect(fixture).toMatchSnapshot();
    });

    beforeEach(() => {
      fixture = TestBed.createComponent(TestSearchComponent);
      component = fixture.componentInstance;
    });

    it('with lvPlaceHolder', () => {
      renderComp({ placeHolder: 'search' });
    });

    // 自动聚焦渲染
    it('with lvFocus', () => {
      renderComp({ focus: true });
    });

    it('with lvLoading', () => {
      renderComp({ loading: true });
    });

    it('with lvDisabled', () => {
      renderComp({ disabled: true });
    });
  });

  describe('work', () => {
    let component: TestSearchComponent;
    let fixture: ComponentFixture<TestSearchComponent>;

    beforeEach(() => {
      fixture = TestBed.createComponent(TestSearchComponent);
      component = fixture.componentInstance;
      jest.spyOn(component, 'search');
      jest.spyOn(component, 'clear');
      fixture.autoDetectChanges();
    });

    // 正常输入后回车触发lvSearch回调
    it('should work when input and enter', fakeAsync(() => {
      fixture.detectChanges();
      const input = fixture.nativeElement.querySelector('.lv-input');
      input.value = 'test';
      input.dispatchEvent(new Event('input'));
      fixture.detectChanges();
      tick(500);

      const e = new KeyboardEvent('keydown', {
        keyCode: 13,
        bubbles: true,
      });
      input.dispatchEvent(e);
      tick(500);
      expect(component.search).toBeCalled();
    }));

    // 输入后可以点击X按钮清空，并触发lvClear回调
    it('should work when clear', fakeAsync(() => {
      fixture.detectChanges();
      const input = fixture.nativeElement.querySelector('.lv-input');
      input.value = 'test';
      input.dispatchEvent(new Event('input'));
      fixture.detectChanges();
      tick(500);

      const clearButton = fixture.nativeElement.querySelector('.lv-search-clear');
      clearButton.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(500);
      expect(input.value).toBe('');
      expect(component.search).toBeCalled();
    }));
  });
});
